package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    public static ExecutorService executorService = Executors.newFixedThreadPool(10);
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start...");
        //runAsync() 没有返回值，不能获取执行结果,supplyAsync()有返回值，可以获取执行结果
        /*CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
        }, executorService);*/
       /* CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果:" + i);
            return i;
        }, executorService).whenComplete((res,excption)->{
            //whenComplete() 可以得到异常信息,但是无法修改返回数据
            System.out.println("异步任务完成了.... 结果:"+res+"...异常:"+excption);
        }).exceptionally((t)->{
            //可以感知异常,同时可以返回默认值数据
            System.out.println("异常信息:"+t.getMessage());
            return 10;
        });*/

        //handle() 方法完成后的处理
        /*CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果:" + i);
            return i;
        }, executorService).handle((res,excption)->{
            //handle() 方法完成后的处理
            if(res!=null){
                return res*2;
            }
            if (excption!=null){
                return 0;
            }
            return 0;
        });*/

        /**
         * 线程串行化
         * CompletableFuture.thenApply 当一个线程依赖另一个线程时，获取上一个任务返回的结果，并返回当前任务的返回值。
         * CompletableFuture.thenAccept 消费处理结果。接收任务的处理结果，并消费处理，无返回结果。
         * CompletableFuture.thenRun)只要上面的任务执行完成，就开始执行 thenRun，只是处理完任务后，执行thenRun 的后续操作。
         * CompletableFuture.thenRun()不能获取到上一部的执行结果,无返回值
         * CompletableFuture.thenAccept()能接受上一步的执行结果,无返回值
         * CompletableFuture.thenApply()能接受上一步的执行结果,有返回值
         */
     /*   CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                    System.out.println("当前线程:" + Thread.currentThread().getId());
                    int i = 10 / 4;
                    System.out.println("运行结果:" + i);
                    return i;
                }, executorService)
                .thenApplyAsync(res -> {
                    System.out.println("任务1结束,结果是:" + res);
                    System.out.println("任务2启动了");
                    return "hello," + res;
                }, executorService);
        *//*        .thenAcceptAsync(res->{
            System.out.println("任务2启动了..."+res);
        },executorService);*//*
       *//*         .thenRunAsync(() -> {
            System.out.println("任务2 启动 了");
        }, executorService);*//*
     */

        /**
         * 俩个任务组合---都要完成
         */
        /*CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1当前线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任务1运行结果:" + i);
            return i;
        }, executorService);

        CompletableFuture<String> future02= CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2当前线程:" + Thread.currentThread().getId());
            System.out.println("任务2结束:" );
            return "hello";
        }, executorService);*/

        //runAfterBothAsync() 组合两个 future，不需要获取 future 的结果，只需两个future 处理完任务后,处理该任务。
        /*future01.runAfterBothAsync(future02,()->{
            System.out.println("任务3开始....");
        },executorService);*/

        //thenAcceptBothAsync() 组合两个 future，需要获取两个future的结果，处理该任务。没有返回值
        /*future01.thenAcceptBothAsync(future02,(f1,f2)->{
            System.out.println("任务3开始....之前的结果是:"+f1+"..."+f2);
        },executorService);*/

        //thenCombineAsync() 组合两个 future，需要获取两个future的结果，处理该任务。有返回值
        /*CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return f1 + ":" + f2 + "-> Hello";
        }, executorService);
        System.out.println("main....end..."+future.get());*/


        /**
         * 两任务组合--一个完成
         * 当两个任务中，任意一个 future 任务完成的时候，执行任务。
         */
        /*CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1当前线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任务1运行结果:" + i);
            return i;
        }, executorService);

        CompletableFuture<Object> future02= CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2当前线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("任务2结束:" );
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }, executorService);*/

        //runAfterEitherAsync()两个任务有一个执行完成，不需要获取 future 的结果，处理任务，也没有返回值。
        /*future01.runAfterEitherAsync(future02,()->{
            System.out.println("任务3开始....");
        },executorService);*/

        //acceptEitherAsync()两个任务有一个执行完成，需要获取 future 的结果，处理任务，没有返回值。
       /* future01.acceptEitherAsync(future02,(res)->{
            System.out.println("任务3开始....之前的结果是:"+res);
        },executorService);*/
        //applyToEitherAsync() 两个任务有一个执行完成，需要获取 future 的结果，处理任务，有返回值。
       /* CompletableFuture<String> future = future01.applyToEitherAsync(future02, (res) -> {
            return res.toString() + "->Hello";
        }, executorService);
        System.out.println("main....end..."+future.get());*/

        /**
         * 多任务组合
         * allOf 等待所有任务执行完，再执行下一步任务。
         * anyOf 只要有一个任务执行完成，就执行下一步任务。
         */
        CompletableFuture<String> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            return "hello.jpg";
        }, executorService);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性信息");
            return "黑色+256G";
        }, executorService);

        CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {

            try {
                Thread.sleep(3000);
                System.out.println("查询商品介绍");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return "华为";
        }, executorService);
      /*  CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
        allOf.get();*/
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future01, future02, future03);
        System.out.println("main....end..."+ anyOf.get());
    }
    public static void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start...");
       /* thread01 thread01 = new thread01();
        thread01.start();*/

//        thread02 thread02 = new thread02();
//        new Thread(thread02).start();
        /*FutureTask<Integer> integerFutureTask = new FutureTask<>(new thread03());
        new Thread(integerFutureTask).start();
        Integer i = integerFutureTask.get();*/
        executorService.execute(new thread02());

        /**
         * 工作顺序
         * 1)、线程池创建，准备好core数量的核心线程，准备接受任务
         * 1.1 core满了,就将再进来的任务放入阻塞队列中。空闲的core就会自己去阻塞队列获取任务执行
         * 1.2、阻塞队列满了，就直接开新线程执行，最大只能开到max指定的数量
         * 1.3、max满了就用RejectedExecutionHandler拒绝任务
         * 1.4、max都执行完成，有很多空闲,在指定的时间keepAliveTime以后，释放max-core这些线程
         * new LinkedBlockingDeque<>()默认容量为Integer最大值,内存会不够
         *
         * 一个线程池 core 7;max20 ，queue:50，100并发进来怎么分配的
         * 7个会立即执行,50个会进入队列,队列满了会多开13个进行,剩下的30个使用拒绝策略执行
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                //核心线程数[一直存在];   线程池中创建好以后就准备就绪的线程数量,就等待来接受异步任务去执行
                200,//maximumPoolSize,最大线程数; 控制资源并发
                10,//keepAliveTime, 如果当前的线程数量大于核心数量,释放空闲的线程,
                // 只要线程空闲时间达到指定的keepAliveTime,就会释放maximumPoolSize-corePoolSize个线程
                TimeUnit.SECONDS,//unit, 线程存活时间的单位;
                new LinkedBlockingDeque<>(100000)
                // workQueue,阻塞队列;如果任务很多,就会放到队列中,只要有线程空闲的话,就会去队列中取任务继续执行
                , Executors.defaultThreadFactory() //threadFactory,线程的创建工厂;
                ,new ThreadPoolExecutor.AbortPolicy()
                //RejectedExecutionHandler handler,当队列和线程池都满了,如果还有任务进来,使用指定的拒绝策略拒绝执行任务;
         );
        //Executors.newCachedThreadPool();创建一个可缓存线程池，如果线程池长度超过处理需要，可灵活回收空闲线程，若无可回收，则新建线程
        //Executors.newFixedThreadPool(); 创建一个定长线程池，可控制线程最大并发数，超出的线程会在队列中等待。
        //Executors.newSingleThreadExecutor();创建一个单线程化的线程池，它只会用唯一的工作线程来执行任务，保证所有任务挨个执行

        //Executors.newScheduledThreadPool();创建一个定长线程池，支持定时及周期性任务执行。
        System.out.println("main....end...");

    }
    public static class thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i= 10/2;
            System.out.println("运行结果:"+i);
        }
    }
    public static class thread02 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i= 10/2;
            System.out.println("运行结果:"+i);
        }
    }

    public static class thread03 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i= 10/2;
            System.out.println("运行结果:"+i);
            return i;
        }
    }
}
